Crypto
Must be included via require
.
Non-Cryptographic Hashing Algorithms
crypto.lua
Hash a string using Lua's version of the DJB2 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.lua(str)) --> 2871868277
crypto.djb2
Hash a string using the DJB2 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.djb2(str)) --> 894552257
crypto.fnv1
Hash a string using the 64-bit FNV1 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.fnv1(str)) --> 9065573210506989167
crypto.fnv1a
Hash a string using the 64-bit FNV1A non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.fnv1a(str)) --> 8618312879776256743
crypto.fnv1a32
Hash a string using the 32-bit FNV1A non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.fnv1a32(str)) --> 3582672807
crypto.joaat
Hash a string using the JOAAT non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.joaat(str)) --> 1045060183
crypto.sdbm
Hash a string using the SDBM non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.sdbm(str)) --> 430867652
crypto.crc32
Hash a string using the CRC32 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
- The initial value for the hash. By default, this is zero.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.crc32(str)) --> 222957957
crypto.crc32c
Hash a string using the CRC32C non-cryptographic hashing algorithm.
Parameters
- The string to hash.
- The initial value for the hash. By default, this is zero.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.crc32c(str)) --> 3381945770
crypto.adler32
Hash a string using the Adler-32 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
- The initial value for the hash. By default, this is zero.
pluto
local crypto = require("crypto")local str = "hello"print(crypto.adler32(str)) --> 103547413
crypto.lookup3
Hash a string using the Lookup3 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.lookup3(str)) --> 1252609637
crypto.times33
Hash a string using the Times33 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.times33(str)) --> 3889643616
crypto.murmur1
Hash a string using the Murmur1 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur1(str)) --> 3154674178
crypto.murmur2
Hash a string using the Murmur2 non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur2(str)) --> 1151865881
crypto.murmur2a
Hash a string using the Murmur2A non-cryptographic hashing algorithm.
Parameters
- The string to hash.
Returns
An integer between 0 and 0xffffffff, inclusive.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur2a(str)) --> 2650573207
crypto.murmur64a
Hash a string using the Murmur64A non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur64a(str)) --> -3190198453633110066
crypto.murmur64b
Hash a string using the Murmur64A non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur64b(str)) --> 7088720765356542432
crypto.murmur2neutral
Hash a string using the Murmur2Neutral non-cryptographic hashing algorithm.
Parameters
- The string to hash.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.murmur2neutral(str)) --> 1151865881
Semi-Cryptographic Hashing Algorithms
crypto.md5
Hash a string using the MD5 semi-cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")local str = "hello world"print(crypto.md5(str)) --> 5eb63bbbe01eeed093cb22bb8f5acdc3print(crypto.md5(str, true)) --> \x5e\xb6\x3b\xbb\xe0\x1e\xee\xd0\x93\xcb\x22\xbb\x8f\x5a\xcd\xc3
Cryptographic Hashing Algorithms
crypto.sha1
Hash a string using the SHA-1 cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")print(crypto.sha1("Pluto")) --> bce8c9aca4120776fad6b517874aa09c46405454print(crypto.sha1("Pluto", true)) --> \xbc\xe8\xc9\xac\xa4\x12\x07\x76\xfa\xd6\xb5\x17\x87\x4a\xa0\x9c\x46\x40\x54\x54
crypto.sha256
Hash a string using the SHA-256 cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")print(crypto.sha256("Pluto")) --> 8dad5f6a7dd2dcd8c35ec2fd7babb499bcad60d27d73fe73eca2ce025dfd3b47print(crypto.sha256("Pluto", true)) --> \x8d\xad\x5f\x6a\x7d\xd2\xdc\xd8\xc3\x5e\xc2\xfd\x7b\xab\xb4\x99\xbc\xad\x60\xd2\x7d\x73\xfe\x73\xec\xa2\xce\x02\x5d\xfd\x3b\x47
crypto.sha384
Hash a string using the SHA-384 cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")print(crypto.sha384("Pluto", false)) --> db890233a919b6745d632633c419e14540ff79f1a89bc4ac194b00e7f913f0f06d5d4d7d6cc2b4aaf9485d223afb8cf0
crypto.sha512
Hash a string using the SHA-512 cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")print(crypto.sha512("Pluto", false)) --> ee8410a8bf9511b94fd6669b5c3e0c4b86e8e4bf7baa8dbd2773d4d6381dd1aecebbe391bef4c6158620ab3f6b794907652d4432c2301d7e1a6caf520565cdf2
crypto.ripemd160
Hash a string using the RIPEMD-160 cryptographic hashing algorithm.
Parameters
- The string to hash.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")print(crypto.ripemd160("Pluto")) --> c2072a85f4a691803b8942709036072086fd9550
crypto.hmac
Authenticates a message using the HMAC construction with the given hash algorithm.
Parameters
- The hash algorithm to use.
"sha1"
,"sha256"
,"sha384"
, or"sha512"
. - The secret key.
- The message to authenticate.
- When set to true, returns raw binary data. false outputs lowercase hex digits. By default, this is false.
pluto
local crypto = require("crypto")local key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"aprint(crypto.hmac("sha256", key, "Hi There")) --> b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7
Cryptographic PRNGs
crypto.random
This is a cryptographically secure PRNG, assuming the platform's implementation of the underlying primitive is secure.
Parameters
This function takes 0-2 integer parameters that define the output range:
- If no arguments are given, an inclusive range from
math.mininteger
tomath.maxinteger
is used. - If 1 argument (
n
) is given, an inclusive range from 1 ton
is used. - If 2 arguments (
l
,u
) are given, an inclusive range froml
tou
is used.
Returns
A random lua integer, in the given range.
pluto
local crypto = require("crypto")print(crypto.random()) -- Prints an integer from math.mininteger to math.maxinteger.print(crypto.random(6)) -- Prints an integer from 1 to 6, like a dice roll.print(crypto.random(10, 20)) -- Prints an integer from 10 to 20.
AES-CBC, AES-CFB
These unauthenticated AES modes take both a key and an IV. The IV must be unique and unpredictable for each encryption session to ensure security.
crypto.encrypt
Parameters
data
— The data to be encrypted.mode
— "aes-cbc-pkcs7" or "aes-cfb-pkcs7" for PKCS#7 padding, or "aes-cbc" or "aes-cfb" if you know what you're doing.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.iv
— Must have a length of 16.
crypto.decrypt
Parameters
data
— The ciphertext to decrypt.mode
— "aes-cbc-pkcs7" or "aes-cfb-pkcs7" for PKCS#7 padding, or "aes-cbc" or "aes-cfb" if you know what you're doing.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.iv
— Must have a length of 16.
Returns the decrypted data on success. Throws an error if the padding was incorrect.
pluto
local crypto = require "pluto:crypto"local key <const> = "A Top Secret Key"-- Encryptlocal iv = range(16):map(|| -> string.char(math.random(0, 255))):concat("")local plain = "Hello, world!"local enc = plain |> crypto.encrypt|"aes-cbc-pkcs7", key, iv|print(dumpvar(enc))-- Decryptprint(crypto.decrypt(enc, "aes-cbc-pkcs7", key, iv)) --> Hello, world!
AES-ECB
This unauthenticated AES mode takes only a key, and is considered to be the weakest. Identical plaintext blocks result in identical ciphertext blocks.
crypto.encrypt
Parameters
data
— The data to be encrypted.mode
— "aes-ecb-pkcs7" for PKCS#7 padding, or "aes-ecb" if you know what you're doing.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.
crypto.decrypt
Parameters
mode
— "aes-ecb-pkcs7" for PKCS#7 padding, or "aes-ecb" if you know what you're doing.data
— The ciphertext to decrypt.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.
Returns the decrypted data on success. Throws an error if the padding was incorrect.
pluto
local crypto = require "pluto:crypto"local key <const> = "A Top Secret Key"-- Encryptlocal plain = "Hello, world!"local enc = plain |> crypto.encrypt|"aes-ecb-pkcs7", key|print(dumpvar(enc)) --> string(16) "`p{����k\21*.>jG"-- Decryptprint(crypto.decrypt(enc, "aes-ecb-pkcs7", key)) --> Hello, world!
AES-GCM
This authenticated AES mode allows for additional data that will be validated although not encrypted, such as a Message Authentication Code (MAC).
crypto.encrypt
Parameters
data
— The data to be encrypted.mode
— Must be "aes-gcm". AES-GCM can deal with unpadded data, hence does not need PKCS#7 padding.aadata
— Authenticated data. Will not be encrypted.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.iv
— Must have a length of 16.
Returns two strings: the ciphertext and the authentication tag.
crypto.decrypt
Parameters
data
— The ciphertext to decrypt.mode
— Must be "aes-gcm".aadata
— Authenticated data.key
— Must have a length of 16, 24 or 32 for 128-, 192-, or 256-bit AES, respectively.iv
— Must have a length of 16.tag
— The authentication tag produced by the "encrypt" procedure.
Returns the decrypted data on success. Throws an error if authentication or unpadding failed.
pluto
local crypto = require "pluto:crypto"local key <const> = "A Top Secret Key"local aadata = "This is Pluto!"-- Encryptlocal iv = range(16):map(|| -> string.char(math.random(0, 255))):concat("")local plain = "Hello, world!"local enc, tag = plain |> crypto.encrypt|"aes-gcm", aadata, key, iv|print(dumpvar(enc))print(dumpvar(tag))-- Decryptprint(crypto.decrypt(enc, "aes-gcm", aadata, key, iv, tag)) --> Hello, world!
RSA
crypto.generatekeypair
Parameters
mode
— Must be "rsa".bits
— A positive integer for a strict bit-length requirement, or a negative integer for a lax requirement. Common values are1024
,2048
, and4096
.
Returns two tables: The public key (consisting of n
and e
), and the private key (consisting of p
and q
). The Bigint class is used for all values.
pluto
local pub, priv = crypto.generatekeypair("rsa", 512)print(dumpvar(pub))--> {--> ["n"] = 11355630182234424425429331560518598643298965915936825610957270519615363349759012613228119611304846673085167794661819394470107090216347491908311079792054357,--> ["e"] = 65537,--> }print(dumpvar(priv))--> {--> ["p"] = 115443384115231951475820445136871322101870729500298182134363293112660251666017,--> ["q"] = 98365361248415863235179644468056200977592391948608651522703704315152579004021,--> }
crypto.derive
Derives a public key from a private key.
Parameters
mode
— Must be "rsa".key
— The private key containingp
andq
.
Returns
The public key corresponding to the private key.
pluto
local { bigint, crypto } = require "pluto:*"local priv = {p = new bigint("115443384115231951475820445136871322101870729500298182134363293112660251666017"),q = new bigint("98365361248415863235179644468056200977592391948608651522703704315152579004021"),}local pub = crypto.derive("rsa", priv)print(pub.n) --> 11355630182234424425429331560518598643298965915936825610957270519615363349759012613228119611304846673085167794661819394470107090216347491908311079792054357print(pub.e) --> 65537
crypto.exportkey
Exports a private key.
Parameters
- The key to export.
- The exchange format to use. Only "pem" is supported right now.
pluto
local { bigint, crypto } = require "pluto:*"local priv = {p = new bigint("115443384115231951475820445136871322101870729500298182134363293112660251666017"),q = new bigint("98365361248415863235179644468056200977592391948608651522703704315152579004021"),}print(crypto.exportkey(priv, "pem"))
-----BEGIN RSA PRIVATE KEY-----MIIBOwIBAAJBANjRKgOuLxSxbL/fFg/3rJeRGGKz0EjxjjuV6QmgjZGq1LpI2KH+TrxVV4L94U0TCFo19vYtV6T4bOH/MlA6kFUCAwEAAQJANcTrfzWpgd99WXkM6uFQiVcHneS7fPeAvziubf+F1E98zwFgLbIOiPSJcVkXc79A2PQZdbGq7dFAxVD0EpIsoQIhAP86o9Ap9KOH4rgZn8ElHyWKO/Cj8m7oHjSmHG/CBGZhAiEA2XjSTZJ37mg3gJOXlMjG4SK15/jRCB1CMx8f4VhBhnUCIQCWK0p3EDiAf1NGPs1gNxc8XzklPVFHMAuVrqbMmrs8AQIhAJ1aqvCuFlFO3zoNkRR64kxsjSq4AqfYY9oRn0OyVFcxAiBjueZ/sI52jgP8+xK2x7coiX5/tDmXCGlp5utUAjk2+Q==-----END RSA PRIVATE KEY-----
crypto.importkey
Imports a private key.
Parameters
- The encoded key.
- The exchange format to use. Only "pem" is supported right now.
pluto
local { bigint, crypto } = require "pluto:*"print(dumpvar(crypto.importkey([[-----BEGIN RSA PRIVATE KEY-----MIIBOwIBAAJBANjRKgOuLxSxbL/fFg/3rJeRGGKz0EjxjjuV6QmgjZGq1LpI2KH+TrxVV4L94U0TCFo19vYtV6T4bOH/MlA6kFUCAwEAAQJANcTrfzWpgd99WXkM6uFQiVcHneS7fPeAvziubf+F1E98zwFgLbIOiPSJcVkXc79A2PQZdbGq7dFAxVD0EpIsoQIhAP86o9Ap9KOH4rgZn8ElHyWKO/Cj8m7oHjSmHG/CBGZhAiEA2XjSTZJ37mg3gJOXlMjG4SK15/jRCB1CMx8f4VhBhnUCIQCWK0p3EDiAf1NGPs1gNxc8XzklPVFHMAuVrqbMmrs8AQIhAJ1aqvCuFlFO3zoNkRR64kxsjSq4AqfYY9oRn0OyVFcxAiBjueZ/sI52jgP8+xK2x7coiX5/tDmXCGlp5utUAjk2+Q==-----END RSA PRIVATE KEY-----]], "pem")))
{["p"] = 115443384115231951475820445136871322101870729500298182134363293112660251666017,["q"] = 98365361248415863235179644468056200977592391948608651522703704315152579004021,}
crypto.encrypt
Parameters
data
— The data to be encrypted.mode
— "rsa-sha1", "rsa-sha256", "rsa-sha384", or "rsa-sha512" for RSA-OAEP with the corresponding hash, "rsa-pkcs1" for PKCS#1 v1.5, or "rsa" if you know what you're doing.key
— The public or private key to use. Commonly, a public key is used to encrypt data.label
— (optional) Associated data/label used for RSA-OAEP. Must match between encryption and decryption.
crypto.decrypt
Parameters
data
— The ciphertext to decrypt.mode
— "rsa-sha1", "rsa-sha256", "rsa-sha384", or "rsa-sha512" for RSA-OAEP with the corresponding hash, "rsa-pkcs1" for PKCS#1 v1.5, or "rsa" if you know what you're doing.key
— The public or private key to use. If the data was encrypted with the public key, the private key is needed to decrypt it.label
— (optional) Associated data/label used for RSA-OAEP. Must match what was provided during encryption.
pluto
local { base64, bigint, crypto } = require "pluto:*"local priv = {p = new bigint("115443384115231951475820445136871322101870729500298182134363293112660251666017"),q = new bigint("98365361248415863235179644468056200977592391948608651522703704315152579004021"),}local pub = crypto.derive("rsa", priv)-- Encryptlocal enc = crypto.encrypt("You know the primes!", "rsa-sha1", pub, "Authenticated Data")print(base64.encode(enc))-- Decryptprint(enc |> crypto.decrypt|"rsa-sha1", priv, "Authenticated Data"|) --> You know the primes!
crypto.sign
Signs a message as per the PKCS#1 v1.5 scheme.
Parameters
data
— The data to sign.mode
— "rsa-sha256" or "rsa-sha1".key
— The private key to use.
crypto.verify
Verifies a message as per the PKCS#1 v1.5 scheme.
Parameters
data
— The data that was signed.mode
— "rsa-sha256" or "rsa-sha1".key
— The public key corresponding to the signer's private key.signature
— The signature produced by the "sign" procedure.
Returns a boolean that indicates if the signature validated successfully.
pluto
local { base64, bigint, crypto } = require "pluto:*"local priv = {p = new bigint("115443384115231951475820445136871322101870729500298182134363293112660251666017"),q = new bigint("98365361248415863235179644468056200977592391948608651522703704315152579004021"),}-- Derive public keylocal pub = {n = priv.p * priv.q, -- 11355630182234424425429331560518598643298965915936825610957270519615363349759012613228119611304846673085167794661819394470107090216347491908311079792054357e = new bigint(0x10001) -- 65537}-- Signlocal msg = "The canary has left the nest."local sig = msg |> crypto.sign|"rsa-sha256", priv|print(base64.encode(sig)) --> un1g04+cwG8WxYDpSlj4PO/hsTqSITgYKycRuR+m3AE6ypLyUCrVHC/0j4M3DeW81ADZVda6TVkC/Ht8EdYeFw==-- Verifyprint(crypto.verify(msg, "rsa-sha256", pub, sig)) --> true
Curve25519
crypto.generatekeypair
Generates a keypair for Curve25519.
Parameters
mode
— Must be "curve25519".
Returns two strings: the public key and the private key, each 32 bytes.
pluto
local crypto = require "pluto:crypto"local pub, priv = crypto.generatekeypair("curve25519")print(priv:tohex())print(pub:tohex())assert(crypto.derive("curve25519", priv) == pub)
crypto.derive
Derives a Curve25519 public key from a private key.
Parameters
mode
— Must be "curve25519".key
— The 32-byte private key.
Returns the corresponding public key.
crypto.x25519
Performs an X25519 Diffie-Hellman exchange on Curve25519.
Parameters
private
— The local 32-byte private key.public
— The peer's 32-byte public key.
Returns the 32-byte shared secret.
pluto
local crypto = require "pluto:crypto"local alice_priv <const> = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a":fromhex()local alice_pub <const> = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a":fromhex()local bob_priv <const> = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb":fromhex()local bob_pub <const> = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f":fromhex()print(crypto.x25519(alice_priv, bob_pub):tohex()) --> 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742print(crypto.x25519(bob_priv, alice_pub):tohex()) --> 4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742
Miscellaneous
crypto.decompress
Decompresses a DEFLATE-compressed string (one might call this an "INFLATE" function). Compatible with gzip and zlib headers and footers.
Parameters
data
— The string to decompress.offset
— Optional starting position insidedata
, usingstring.sub
semantics. Defaults to the beginning ofdata
. To provide anoffset
without a decompressed size, passnil
as the third argument.decompressed_size
— Optional size of the decompressed output. When only two arguments are given, the second argument is treated asdecompressed_size
.
Returns
- The decompressed string.
- A table with extra information:
compressed_size
,checksum_present
,checksum_mismatch
pluto
local deflated = "\xF3\x48\xCD\xC9\xC9\xD7\x51\x08\xC8\x29\x2D\xC9\x57\x04"local decompressed, info = require"crypto".decompress(deflated)print(decompressed) --> Hello, Pluto!print(info.compressed_size) --> 14print(info.checksum_present) --> falseprint(info.checksum_mismatch) --> false-- Decompress from an offsetdecompressed, info = require"crypto".decompress("Don't mind me" .. deflated, 14, nil)print(decompressed) --> Hello, Plutoprint(info.compressed_size) --> 14